package com.net.xpay.common.service.impl;

import com.net.xpay.common.domain.DailyTaskRecord;
import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.stat.PartnerUserDayStat;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.stat.PartnerUserDayStatManager;
import com.net.xpay.common.model.search.UserSearchModel;
import com.net.xpay.core.manager.ChargeRecordManager;
import com.net.xpay.core.manager.PayTransBatchManager;
import com.net.xpay.core.manager.safePay.SafePayBatchManager;
import com.net.xpay.core.model.PartnerUserPayTransDayStatModel;
import com.net.xpay.core.model.PartnerUserSafePayTransDayStatModel;
import com.net.common.util.LocalDateUtil;
import com.net.xpay.common.service.PartnerUserDayStatService;
import com.net.shard.ShardUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class PartnerUserDayStatServiceImpl implements PartnerUserDayStatService {

    @Autowired
    private PayTransBatchManager payTransBatchManager;

    @Autowired
    private SafePayBatchManager safePayBatchManager;

    @Autowired
    private UserManager userManager;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private ChargeRecordManager chargeRecordManager;

    @Autowired
    private PartnerUserDayStatManager partnerUserDayStatManager;


    @Override
    public void statPartnerUserDayStat(LocalDate day, DailyTaskRecord record) {
        //冻结的用户不统计 只统计正常的
        UserSearchModel searchModel = new UserSearchModel();
        List<Long> userIds = userManager.listIds(searchModel);
        record.setTotalCount((long) userIds.size());
        log.info("statPartnerUserDayStat userIds={}", userIds);
        if (CollectionUtils.isEmpty(userIds)) {
            return;
        }
        for (Long userId : userIds) {
            try {
                doPartnerUserDayStat(userId, day);
            } catch (Exception e) {
                log.error("statPartnerUserDayStat error|userId={}", userId, e);
                record.setFailedCount(record.getFailedCount() + 1L);
                continue;
            }
            record.setSuccessCount(record.getSuccessCount() + 1L);
        }
    }

    @Override
    public void doPartnerUserDayStat(Long userId, LocalDate day) {
        User user = userManager.getById(userId);
        if (user.getPartnerId() == null) {
            //没有合伙人的不统计
            return;
        }
        //注册时间在统计时间之后的不统计
        if (user.getRegisterTime().toLocalDate().isAfter(day)) {
            return;
        }
        PartnerUserDayStat partnerUserDayStat = new PartnerUserDayStat();
        // 通过userID获取到userShard
        UserShard userShard = userShardManager.getById(userId);
        try {
            // 切库处理
            ShardUtil.setShardContext(userShard.getShardId());

            // 先去判断该用户当天统计记录是否存在
            partnerUserDayStat.setDay(day);
            partnerUserDayStat.setYear(day.getYear());
            partnerUserDayStat.setMonth(day.getMonthValue());
            partnerUserDayStat.setUserId(userId);
            partnerUserDayStat.setPartnerId(user.getPartnerId());
            boolean exitRecord = hasStated(partnerUserDayStat);
            if (exitRecord) {
                log.warn("doPartnerUserDayStat the record of userId={}|day={} is already exist", userId, day);
                return;
            }

            // 获取当天的起始时间和终止时间 终止时间保留在23:59:59.999999999
            LocalDateTime minEndTime = LocalDateUtil.getDayStart(day);
            LocalDateTime maxEndTime = LocalDateUtil.getDayEnd(day);
            //统计查询
            //chargeRecord表统计
            long serviceChargeFee = chargeRecordManager.sumUserServiceChargeFeeByDay(user.getId(),minEndTime,maxEndTime);
            //payTransBatch表统计
            PartnerUserPayTransDayStatModel partnerUserPayTransDayStatModel = payTransBatchManager.sumPartnerUserPayTransDay(user.getId(),minEndTime,maxEndTime);
            //safePayTransBatch表统计
            PartnerUserSafePayTransDayStatModel safePayTransDayStatModel = safePayBatchManager.sumPartnerUserSafePayTransDay(user.getId(),minEndTime,maxEndTime);


            partnerUserDayStat.setServiceChargeFee(new BigDecimal(serviceChargeFee).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));

            partnerUserDayStat.setPayTransCount(partnerUserPayTransDayStatModel.getPayTransCount());
            partnerUserDayStat.setPayTransSuccessCount(partnerUserPayTransDayStatModel.getPayTransSuccessCount());
            partnerUserDayStat.setPayTransFailCount(partnerUserPayTransDayStatModel.getPayTransFailCount());
            partnerUserDayStat.setPayTransServicePrice(new BigDecimal(partnerUserPayTransDayStatModel.getPayTransServicePrice()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));
            partnerUserDayStat.setPayTransAmount(partnerUserPayTransDayStatModel.getPayTransAmount());
            partnerUserDayStat.setPayTransSuccessAmount(partnerUserPayTransDayStatModel.getPayTransSuccessAmount());
            partnerUserDayStat.setPayTransFailAmount(partnerUserPayTransDayStatModel.getPayTransFailAmount());
            partnerUserDayStat.setTotalPayTransPartnerBenefit(new BigDecimal(partnerUserPayTransDayStatModel.getTotalPayTransPartnerBenefit()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));

            partnerUserDayStat.setSafePayTransCount(safePayTransDayStatModel.getSafePayTransCount());
            partnerUserDayStat.setSafePayTransSuccessCount(safePayTransDayStatModel.getSafePayTransSuccessCount());
            partnerUserDayStat.setSafePayTransFailCount(safePayTransDayStatModel.getSafePayTransFailCount());
            partnerUserDayStat.setSafePayTransAmount(safePayTransDayStatModel.getSafePayTransAmount());
            partnerUserDayStat.setSafePayTransSuccessAmount(safePayTransDayStatModel.getSafePayTransSuccessAmount());
            partnerUserDayStat.setSafePayTransFailAmount(safePayTransDayStatModel.getSafePayTransFailAmount());
            partnerUserDayStat.setSafePayTransServicePrice(new BigDecimal(safePayTransDayStatModel.getSafePayTransServicePrice()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));
            partnerUserDayStat.setTotalSafePayTransPartnerBenefit(new BigDecimal(safePayTransDayStatModel.getTotalSafePayTransPartnerBenefit()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));

            //总和数据入库
            partnerUserDayStat.setTotalCount(partnerUserDayStat.getPayTransCount() + partnerUserDayStat.getSafePayTransCount());
            partnerUserDayStat.setTotalSuccessCount(partnerUserDayStat.getPayTransSuccessCount() + partnerUserDayStat.getSafePayTransSuccessCount());
            partnerUserDayStat.setTotalFailCount(partnerUserDayStat.getPayTransFailCount() + partnerUserDayStat.getSafePayTransFailCount());

            partnerUserDayStat.setTotalServicePrice(partnerUserDayStat.getPayTransServicePrice().add(partnerUserDayStat.getSafePayTransServicePrice()));

            partnerUserDayStat.setTotalTransAmount(partnerUserDayStat.getPayTransAmount().add(partnerUserDayStat.getSafePayTransAmount()));
            partnerUserDayStat.setTotalSuccessTransAmount(partnerUserDayStat.getPayTransSuccessAmount().add(partnerUserDayStat.getSafePayTransSuccessAmount()));
            partnerUserDayStat.setTotalFailTransAmount(partnerUserDayStat.getPayTransFailAmount().add(partnerUserDayStat.getSafePayTransFailAmount()));

            partnerUserDayStat.setTotalPartnerBenefit(partnerUserDayStat.getTotalPayTransPartnerBenefit().add(partnerUserDayStat.getTotalSafePayTransPartnerBenefit()));
            partnerUserDayStatManager.save(partnerUserDayStat);
        } finally {
            ShardUtil.cleanShardContext();
        }
    }


    /**
     * @param partnerUserDayStat : 需要查询的数据
     * @return void
     * @Description:[判断partnerUserDayStat中是否已经存在了要插入的数据]
     * @author 
     * @date 2020/9/9 19:23
     */
    private boolean hasStated(PartnerUserDayStat partnerUserDayStat) {
        LocalDate day = partnerUserDayStat.getDay();
        Long userId = partnerUserDayStat.getUserId();
        // 尝试通过时间加id获取数据
        PartnerUserDayStat partnerUserDayStatRecord = partnerUserDayStatManager.findByDayAndUserId(day, userId);
        // 若果查到了数据，表示不需要在插入记录了
        return partnerUserDayStatRecord != null;
    }
}
